package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.assistant.common.vo.BaseVO;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.data.core.util.PagerUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.enums.*;
import com.jwsoft.manager.common.vo.eduDataTask.*;
import com.jwsoft.manager.common.vo.eduDataTaskDetail.EduDataTaskDetailQueryVO;
import com.jwsoft.manager.common.vo.eduDataTaskDetail.EduDataTaskDetailVO;
import com.jwsoft.manager.core.dao.model.EduDataTask;
import com.jwsoft.manager.core.dao.model.EduDataTaskDetail;
import com.jwsoft.manager.core.dao.service.EduDataTaskDetailService;
import com.jwsoft.manager.core.dao.service.EduDataTaskService;
import com.jwsoft.manager.core.integration.EduDataTaskDetailIntegration;
import com.jwsoft.manager.core.integration.EduDataTaskIntegration;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据备份任务表业务实现类
 *
 * @author zhiyuan
 * @since 2023-09-13
 */
@ApiService(funcCode = "eduDataTask", title = "数据备份任务表")
@Slf4j
public class EduDataTaskIntegrationImpl implements EduDataTaskIntegration {

    @Autowired
    public EduDataTaskService eduDataTaskService;

    @Autowired
    public EduDataTaskDetailService eduDataTaskDetailService;

    @Autowired
    public EduDataTaskDetailIntegration eduDataTaskDetailIntegration;

    @Override
    @OpApi(funcCode = "eduDataTask0001", title = "数据备份任务表分页查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduDataTaskVO> getList(EduDataTaskQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        QueryWrapper<EduDataTask> queryWrapper = new QueryWrapper<>();
        if (vo.getYear()!=null){
            queryWrapper.lambda().eq(EduDataTask::getYear,vo.getYear());
        }
        if (StringUtils.isNotBlank(vo.getTaskName())){
            queryWrapper.lambda().like(EduDataTask::getTaskName,vo.getTaskName());
        }
        List<EduDataTask> list = eduDataTaskService.list(queryWrapper);
        for (EduDataTask task:list){
            if ("0".equals(task.getStatus())){
                task.setStatus("待处理");
            }
            if ("1".equals(task.getStatus())){
                task.setStatus("待迁移");
            }
            if ("2".equals(task.getStatus())){
                task.setStatus("待加密");
            }
            if ("3".equals(task.getStatus())){
                task.setStatus("待销毁");
            }
            if ("4".equals(task.getStatus())){
                task.setStatus("完成");
            }
            if("1".equals(task.getErrorFlag())){
                task.setErrorFlag("是");
            }else{
                task.setErrorFlag("否");
            }
        }
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduDataTask> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduDataTaskVO> resultList = Convert.toList(EduDataTaskVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduDataTask0002", title = "数据备份任务表根据主键查询详情", funcType = FuncTypeEnum.query)
    public EduDataTaskVO getById(EduDataTaskKeyVO vo) {
        EduDataTask entity = eduDataTaskService.getById(vo.getTaskId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduDataTaskVO result = Convert.convert(EduDataTaskVO.class, entity);
        return result;
    }

    /**
     * 保存前统一校验
     */
    @Override
    @OpApi(funcCode = "eduDataTask0003", title = "数据备份任务表保存前校验", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduDataTaskVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "eduDataTask0004", title = "数据备份任务表新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduDataTask0004",
            operationName = "数据备份任务表新增",
            dataType = "taskId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduDataTaskVO add(EduDataTaskVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduDataTask entity = Convert.convert(EduDataTask.class, vo);
        eduDataTaskService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setTaskId(entity.getTaskId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduDataTask0005", title = "数据备份任务表修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "eduDataTask0005",
            operationName = "数据备份任务表修改",
            dataType = "taskId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduDataTaskVO edit(EduDataTaskVO vo) {
        if (ObjectUtils.isEmpty(vo.getTaskId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduDataTask oldEntity = eduDataTaskService.getById(vo.getTaskId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduDataTask entity = Convert.convert(EduDataTask.class, vo);
        eduDataTaskService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduDataTask0006", title = "数据备份任务表根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "eduDataTask0006",
            operationName = "数据备份任务表删除",
            dataType = "taskId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduDataTaskKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getTaskId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduDataTask entity = eduDataTaskService.getById(vo.getTaskId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        ArrayList<String> optionStatus = new ArrayList<>();
        optionStatus.add("0");
        optionStatus.add("1");
        if (!optionStatus.contains(entity.getStatus())){
            throw new AppException(entity.getTaskName()+"任务已经处理过数据，不能进行删除操作！");
        }
        List<EduDataTaskDetail> dataTaskDetailList = eduDataTaskDetailService.list
                (new QueryWrapper<EduDataTaskDetail>().lambda().eq(EduDataTaskDetail::getTaskId, entity.getTaskId()));
        Boolean handleFlag = false;
        for (EduDataTaskDetail task : dataTaskDetailList){
            //第一步数据迁移未成功不能删除
            if (BoolEnum.TRUE.getType().equalsIgnoreCase(task.getMigrationStatus())){
                handleFlag = true;
                throw new AppException(task.getHandleTable()+"已执行数据迁移，不能进行删除操作！");
            }
        }
        if (!handleFlag) {
            //删除子任务
            eduDataTaskDetailService.removeBatchByIds(dataTaskDetailList);
            //删除主任务
            eduDataTaskService.removeById(vo.getTaskId());
        }
    }

    @Override
    @OpApi(funcCode = "eduDataTask0007", title = "数据备份表查询", funcType = FuncTypeEnum.query)
    public List<EduDataTableVO> queryDataTable(BaseVO vo) {
        List<EduDataTableVO> tableInfoList = new ArrayList<>();
        //将枚举配置的表信息查询出来进行转换为实体类对象
        for (DataTaskEnum dataTaskEnum : DataTaskEnum.values()) {
            EduDataTableVO tableInfo = new EduDataTableVO();
            tableInfo.setTable(dataTaskEnum.getTable());
            tableInfo.setTableName(dataTaskEnum.getTableName());
            tableInfoList.add(tableInfo);
        }
        return tableInfoList;
    }

    @OpApi(funcCode = "eduDataTask0008", title = "数据备份任务初始化", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduDataTask0008",
            operationName = "数据备份任务初始化",
            dataType = "taskId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    @Override
    public void initDataTable(EduDataTaskInitVO vo) {
        if (ObjectUtils.isEmpty(vo.getYear())) {
            throw new AppException("初始化年份不能为空");
        }
        List<EduDataTableVO> tableInfo = new ArrayList<>();
        if (CollectionUtils.isEmpty(vo.getTables())) {
            throw new AppException("数据库表不能为空！");
        } else {
            List<String> tables = vo.getTables();
            //选择了主表，就需要连同附表一起选上,附表同理
            Map<String, String> tableMap = new HashMap<>();
            tableMap.put(DataTaskEnum.EDU_SOCIAL_SECURITY.getTable(),DataTaskEnum.EDU_SOCIAL_SECURITY_DETAIL.getTable());
            tableMap.put(DataTaskEnum.EDU_SOCIAL_SECURITY_DETAIL.getTable(),DataTaskEnum.EDU_SOCIAL_SECURITY.getTable());
            tableMap.put(DataTaskEnum.EDU_HOUSE.getTable(), DataTaskEnum.EDU_HOUSE_DETAIL.getTable());
            tableMap.put(DataTaskEnum.EDU_HOUSE_DETAIL.getTable(),DataTaskEnum.EDU_HOUSE.getTable());
            tableMap.put(DataTaskEnum.EDU_STUDENT_ENROLL_PRE.getTable(),DataTaskEnum.EDU_STUDENT_ENROLL_FAMILY.getTable());
            tableMap.put(DataTaskEnum.EDU_STUDENT_ENROLL_FAMILY.getTable(),DataTaskEnum.EDU_STUDENT_ENROLL_PRE.getTable());


            //使用set来进行存储表名，保证初始化的表是唯一存在的
            Set<String> newTablesSet = new HashSet<>(tables);
            for (String tableName : tables) {
                String relatedTable = tableMap.get(tableName);
                if (relatedTable != null) {
                    newTablesSet.add(relatedTable);
                }
            }

            for (String table : newTablesSet) {
                String tableName = DataTaskEnum.getBytable(table);
                if (!ObjectUtils.isEmpty(tableName)) {
                    EduDataTableVO tableVO = new EduDataTableVO();
                    tableVO.setTable(table);
                    tableVO.setTableName(tableName);
                    tableInfo.add(tableVO);
                } else {
                    throw new AppException("需要初始化的表名不存在，请检查后重试");
                }
            }
        }

        //创建初始化任务
        EduDataTask dataTask = new EduDataTask();
        dataTask.setTaskId(IdUtil.simpleUUID());
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String nowDate = dateFormat.format(date);
        dataTask.setTaskName(nowDate + "数据备份任务");
        dataTask.setYear(vo.getYear());
        //创建好初始化任务，设置为待迁移状态
        dataTask.setStatus(EduDataTaskTypeEnum.dqy.getType());
        eduDataTaskService.save(dataTask);

        //根据传入的表，初始化详情数据
        List<EduDataTaskDetail> eduDataTaskDetails = tableInfo.stream().map(table -> {
            EduDataTaskDetail taskDetail = new EduDataTaskDetail();
            taskDetail.setTaskDetailId(IdUtil.simpleUUID());
            taskDetail.setTaskId(dataTask.getTaskId());
            taskDetail.setHandleTable(table.getTable());
            String historyTable = table.getTable().replaceAll("\\bedu", "eduh");
            String tempTable = table.getTable().replaceAll("\\bedu", "edut");
            taskDetail.setMigrationTable(historyTable);
            taskDetail.setTempTable(tempTable);
            taskDetail.setYear(vo.getYear());
            taskDetail.setCleanStatus(EduStatusTypeEnum.dcl.getType());
            taskDetail.setEncryptStatus(EduStatusTypeEnum.dcl.getType());
            taskDetail.setMigrationStatus(EduStatusTypeEnum.dcl.getType());
            taskDetail.setTempCleanStatus(EduStatusTypeEnum.dcl.getType());
            return taskDetail;
        }).collect(Collectors.toList());
        //将初始化详情任务进行插入表中
        eduDataTaskDetailService.saveBatch(eduDataTaskDetails);
    }

    @OpApi(funcCode = "eduDataTask0009", title = "备份任务数据迁移", funcType = FuncTypeEnum.update)
    @Override
    public void dataTaskMigration(EduOperationParamVO vo) {
        if (ObjectUtils.isEmpty(vo.getTaskId())) {
            throw new AppException("任务Id不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getTaskDetailIds())) {
            throw new AppException("任务详情Id不能为空！");
        }
        EduDataTaskKeyVO eduDataTaskKeyVO = new EduDataTaskKeyVO();
        eduDataTaskKeyVO.setTaskId(vo.getTaskId());
        EduDataTaskVO dataTask = this.getById(eduDataTaskKeyVO);
        //判断任务是否处于带迁移
        if (!EduDataTaskTypeEnum.dqy.getType().equals(dataTask.getStatus())) {
            throw new AppException("当前任务不是待迁移状态，无需进行数据迁移！");
        }
        List<String> taskDetailIds = vo.getTaskDetailIds();
        try {
            for (String taskDetailId : taskDetailIds) {
                //根据年度，和任务详情id去执行单业务数据迁移
                EduDataTaskDetailQueryVO detailVO = new EduDataTaskDetailQueryVO();
                detailVO.setTaskDetailId(taskDetailId);
                detailVO.setYear(dataTask.getYear());
                detailVO.setTaskId(dataTask.getTaskId());
                try {
                    eduDataTaskDetailIntegration.dataTaskMigration(detailVO);
                }catch(AppException e){
                    throw new AppException(e.getMessage());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        } catch (AppException e) {
            throw new AppException(e.getMessage());
        } catch (Exception e) {
            //如果遇到异常，需要修改主任务状态
            dataTask.setErrorFlag(BoolEnum.TRUE.getType());
            String errorMessage = e.getMessage();
            if (errorMessage.length() > 500) {
                errorMessage = errorMessage.substring(0, 500);
            }
            dataTask.setErrorRemarks(errorMessage);
            EduDataTask eduDataTask = Convert.convert(EduDataTask.class, dataTask);
            eduDataTaskService.updateById(eduDataTask);
            throw new AppException(e);
        }
    }

    @OpApi(funcCode = "eduDataTask0010", title = "备份任务数据加密", funcType = FuncTypeEnum.update)
    @Override
    public void dataTaskEncrypt(EduOperationParamVO vo) {
        if (ObjectUtils.isEmpty(vo.getTaskId())) {
            throw new AppException("任务Id不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getTaskDetailIds())) {
            throw new AppException("任务详情Id不能为空！");
        }
        EduDataTask dataTask = eduDataTaskService.getById(vo.getTaskId());
        if (ObjectUtils.isEmpty(dataTask)) {
            throw new AppException("查询不到详细信息!");
        }
        //判断任务是否未待加密
        if (!EduDataTaskTypeEnum.djm.getType().equals(dataTask.getStatus())) {
            //如果是待迁移
            if (EduDataTaskTypeEnum.dqy.getType().equals(dataTask.getStatus())) {
                throw new AppException("当前任务还为完成数据迁移，请完成迁移后重试!");
            } else {
                throw new AppException("当前任务不是待加密状态，无法进行数据加密！");
            }
        }
        //根据详情任务id处理详情任务
        List<String> taskDetailIds = vo.getTaskDetailIds();
        try {
            for (String taskDetailId : taskDetailIds) {
                EduDataTaskDetailQueryVO detailVO = new EduDataTaskDetailQueryVO();
                detailVO.setTaskDetailId(taskDetailId);
                detailVO.setYear(dataTask.getYear());
                detailVO.setTaskId(dataTask.getTaskId());
                //单业务数据加密
                try {
                    eduDataTaskDetailIntegration.dataTaskDetailEncrypt(detailVO);
                }catch(AppException e){
                    throw new AppException(e.getMessage());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        } catch (AppException e) {
            log.error(e.getMessage());
            throw new AppException(e.getMessage());
        } catch (Exception e) {
            dataTask.setErrorFlag(BoolEnum.TRUE.getType());
            dataTask.setErrorRemarks(e.getMessage());
            EduDataTask eduDataTask = Convert.convert(EduDataTask.class, dataTask);
            eduDataTaskService.updateById(eduDataTask);
            throw new RuntimeException(e);
        }
    }

    @OpApi(funcCode = "eduDataTask0011", title = "备份任务数据核销", funcType = FuncTypeEnum.other)
    @Override
    public void dataTaskClean(EduOperationParamVO vo) {
        if (ObjectUtils.isEmpty(vo.getTaskId())) {
            throw new AppException("任务Id不能为空！");
        }
        if (ObjectUtils.isEmpty(vo.getTaskDetailIds())) {
            throw new AppException("任务详情Id不能为空！");
        }
        EduDataTaskKeyVO eduDataTaskKeyVO = new EduDataTaskKeyVO();
        eduDataTaskKeyVO.setTaskId(vo.getTaskId());
        EduDataTaskVO dataTask = this.getById(eduDataTaskKeyVO);
        //判断任务是否处于待销毁状态
        if (!EduDataTaskTypeEnum.dxh.getType().equalsIgnoreCase(dataTask.getStatus())){
            throw new AppException("当前任务状态不是待销毁状态，无法进行数据清洗");
        }
        List<String> taskDetailIds = vo.getTaskDetailIds();
        try{
            for (String taskDetailId : taskDetailIds) {
                EduDataTaskDetailQueryVO detailVO = new EduDataTaskDetailQueryVO();
                detailVO.setTaskDetailId(taskDetailId);
                detailVO.setYear(dataTask.getYear());
                detailVO.setTaskId(dataTask.getTaskId());
                //单业务数据核销
                try {
                    eduDataTaskDetailIntegration.dataTaskDetailClean(detailVO);
                }catch (AppException e){
                    throw new AppException(e);
                }catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }catch (AppException e){
            //发生自定义异常，进行跳过，处理其他业务
            log.error(e.getMessage());
        }catch (Exception e){
            //发生系统异常需要停下来，修改主任务状态
            dataTask.setErrorFlag(BoolEnum.TRUE.getType());
            dataTask.setErrorRemarks(e.getMessage());
            EduDataTask eduDataTask = Convert.convert(EduDataTask.class, dataTask);
            eduDataTaskService.updateById(eduDataTask);
            throw new RuntimeException(e);
        }
    }

    @Override
    @OpApi(funcCode = "eduDataTask0012", title = "备份子任务查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduDataTaskDetailVO> getSubtaskList(EduDataTaskDetailVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());

        List<EduDataTaskDetail> list = eduDataTaskDetailService.list(new QueryWrapper<EduDataTaskDetail>().lambda().eq(EduDataTaskDetail::getTaskId, vo.getTaskId()));

        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduDataTaskDetail> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduDataTaskDetailVO> resultList = Convert.toList(EduDataTaskDetailVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

}
